home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / Documentation / Engineering Notes / Threads < prev    next >
Encoding:
Text File  |  1996-09-19  |  6.1 KB  |  129 lines  |  [TEXT/ttxt]

  1. OpenDoc
  2. Development
  3. Framework
  4.                                                                                                                                                                                      
  5. ODF support for Threads
  6. ODF Release 2                                                                                                                                                             
  7.  
  8. The Threads subsystem contains classes which assist you in using threads in OpenDoc parts.  This subsystem is used by ODF's Cyberdog support; for Cyberdog-related details, see the Internet Engineering Notes.
  9.  
  10.  
  11. Table of Contents
  12. ---------------------------------
  13. • FW_CThread Class
  14. • Mutexes, Semaphores, etc
  15. • Issues When Using Threads
  16.  
  17.  
  18.  
  19. FW_CThread Class
  20.  
  21. FW_CThread is a wrapper class for platform threads. It has methods for sleeping, suspending, and resuming a thread. It also catches exceptions that might accidentally be propogated to the entry point of a thread. Finally it declares a unique SOM Environment for each thread. FW_CThread is declared in FWODThrd.h in the OS layer.
  22.  
  23. FW_CThread::FW_CThread (void* parameters = kODNULL, FW_ThreadProcedure procedure = kODNULL)
  24. For your convenience, the constructor takes an optional void* parameter; this will be stored in the fParameters instance variable. The procedure parameter allows you to pass a pointer to a global function into FW_CThread; this will be executed by the default implementation of Run. The combination of these two parameters allows you to run code in a thread without having to subclass FW_CThread.
  25.  
  26. FW_CThread::~FW_CThread ()
  27. Kills the thread. You must delete every thread you create. Usually you will do this after the thread has finished running, but you may also kill a running thread (for example, if your part is deleted then you would need to terminate any threads immediately).
  28.  
  29. void FW_CThread::Sleep (long ticks)
  30. Use this methods to put a thread to sleep. It works whether you call it from within the thread or from a different thread. A tick is 1/60th of a second. It is currently not safe to Resume or Kill a sleeping thread; you must allow it to wake up.
  31.  
  32. void FW_CThread::Suspend ()
  33. Stops a thread from executing until Resume is called; this method can be called from within a thread or from a different one.
  34.  
  35. void FW_CThread::Resume ()
  36. Causes a thread that has been Suspended to continue executing.
  37.  
  38. virtual void FW_CThread::Run (Environment* ev)
  39. You may implement the code of a thread by subclassing it and overriding Run. Alternatively, if you pass a function pointer and void* parameter into the constructor, the default implementation of Run will call it (and pass the parameter).
  40.  
  41. For any thread of moderate complexity, you will want to make a subclass and implement Run, like so:
  42.  
  43. class MyCalculationThread: public FW_CThread {
  44. public:
  45.     MyCalculationThread (MyPart* part, int parameter, const FW_CString& name);
  46.     virtual void Run (Environment* ev);
  47. private:
  48.     MyPart* fPart;
  49.     int fLevel;
  50.     FW_CString fName;
  51. };
  52.  
  53. MyCalculationThread::MyCalculationThread (MyPart* part, int parameter, const FW_CString& name)
  54. :   fPart (part)
  55.     fLevel (parameter),
  56.     fName (name)
  57. {
  58. }
  59.  
  60. void MyCalculationThread::Run (Environment* ev)
  61. {
  62.     // do something here
  63.     int result = 1;
  64.     for (int i = 2; i <= fLevel; i++)
  65.         result *= i;
  66.     // presumably you would call the part when you are done
  67.     fPart->DidCalculation (result);
  68. }
  69.  
  70. void MyPart::DoMenuCommand (int id)
  71. {
  72.     if (id == cDoCalculate && !fMyThread)
  73.         fMyThread = MyCalculationThread ();
  74. }
  75.  
  76.  
  77.  
  78. Mutexes, Semaphores, etc.
  79.  
  80. ODF doesn't have any public and supported classes for managing access to resources. There is a simple critical section class, FW_CThreadCriticalState, but it was only intended for internal use. Cross-platform classes will appear in ODF 3.
  81.  
  82.  
  83.  
  84. Issues When Using Threads
  85.  
  86. (1) Avoid creating objects on the stack.
  87.  
  88. When a thread is killed, stack-based objects are not destroyed (this is a C++ problem, not specific to OpenDoc). If you have objects which must be destroyed, declare them as members of your thread class.
  89.  
  90. Here is unsafe code:
  91.  
  92. void MyCalculationThread::Run (Environment* ev)
  93. {
  94.     int tempValue; // Ok since it's just an int.
  95.     FW_CString tempString; // Unsafe! If this thread is killed the string will not be disposed of.
  96.     // do something with tempString
  97. }
  98.  
  99. This is safer:
  100.  
  101. class MyCalculationThread… {
  102.     …
  103.     FW_CString fTempString;
  104. }
  105.  
  106. void MyCalculationThread::Run (Environment* ev)
  107. {
  108.     int tempValue; // Ok since it's just an int.
  109.     // do something with fTempString
  110. }
  111.  
  112. In general, local stack-based objects should be declared as member variables. This is inconvenient, but C++ doesn't provide a mechanism to handle multiple stacks. We will try to provide workarounds in the future, but destruction of stack-based objects is compiler-specific and we can't be sure we'll be able to do anything about it.
  113.  
  114. (2) Make sure you delete your threads!
  115.  
  116. ODF does not keep track of threads for your; that's your responsibility. If you spawn threads you must take care to delete them; this is especially important since your part can go away before a thread is complete (for example, if it is embedded then a user can delete it).
  117.  
  118. (3) Beware of reentrancy.
  119.  
  120. Portions of OpenDoc and other parts may not react well to being called from threads (other than the main thread). For safety you should restrict threads to calling only your own code. If you do call OpenDoc, be aware that it may call back into your part (for example during frame negotiation).
  121.  
  122. ODF itself is not entirely thread-safe. For instance the graphics system won't deal well with graphic contexts existing simultaneously in multiple threads (you can do it as long as you don't Yield when a context is in scope).
  123.  
  124. (4) Threads Require Native Exceptions
  125.  
  126. ODF’s emulated exception handling is not compatible with threads. This means that you must use a compiler which supports native exceptions. CodeWarrior supports native exceptions and this is the default for ODF2, so for most people this won't be a problem.
  127.  
  128. © 1993 - 1996 Apple Computer, Inc. All rights reserved.
  129. Apple, the Apple Logo, Macintosh, and OpenDoc are trademarks of Apple Computer, Inc., registered in the United States and other countries.